home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / tvx.arc / TVX-IO.C < prev    next >
C/C++ Source or Header  |  1989-07-30  |  42KB  |  1,870 lines

  1. /* ---------------------------- tvx_io.c ------------------------------- */
  2. #include "tvx_defs.ic"
  3. #include "tvx_glbl.ic"
  4.  
  5. #define SWITCH '-'
  6. #define FILESEP '.'
  7.  
  8. #ifdef MSDOS
  9. #define TEMPEXT ".$$1"        /* name of temporary file */
  10. #define BACKEXT ".BAK"        /* name of backup file */
  11. #endif
  12.  
  13. #ifdef OSCPM
  14. #define TEMPEXT ".$$1"        /* name of temporary file */
  15. #define BACKEXT ".BAK"        /* name of backup file */
  16. #endif
  17.  
  18. #ifdef GEMDOS
  19. #define TEMPEXT ".Z1X"        /* name of temporary file */
  20. #define BACKEXT ".BAK"        /* name of backup file */
  21. #endif
  22.  
  23. #ifdef UNIX
  24. #define BACKEXT ".B"        /* name of backup file */
  25. #endif
  26.  
  27.     FILE *fopen();
  28.  
  29. /* local globals (used by tv terminal driver section) */
  30.  
  31.     static int linptr; /* common "linot" */
  32.     static char linout[242];
  33.  
  34.     static char stemp[FNAMESIZE+1];
  35.  
  36. /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  37.  
  38.     FILE IO section
  39.  
  40.    File handling algorithm:
  41.  
  42.     The original name specified on command line is called orig_file.
  43.     It will remain untouched throughout the editing session.  At the
  44.     very end (normal exit), it will be renamed to the ".BAK" name.
  45.  
  46.     source_file is the current name of the file with source.  It will
  47.     orignally be the same as orig_file, but may change to a generated
  48.     scratch name depending on the operating system.  source_file is
  49.     always the lastest fully written version of the file (like after
  50.     file beginning, for example). 
  51.  
  52.     work_file is the output file.  On normal exit, this is the
  53.     file renamed to dest_file.  On buffer beginning, it will be
  54.     moved to source_file, possibly after renameing.
  55.     
  56.     dest_file is the ultimate destination file.  This name is not
  57.     actually used until the final rename on normal exit.  It is
  58.     checked to be sure it is a valid name to be opened, however.
  59.  
  60.    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  61.  
  62. /* =============================>>> ABORT <<<============================= */
  63.   abort()
  64.   {    /* abort - close files, abort operation */
  65.  
  66.     char rply[4];
  67.  
  68.     tvclr();
  69.     ask("Abort, are you sure? ",rply,1);
  70.     if (clower(rply[0]) != 'y')
  71.       {
  72.     verify(1);
  73.     return;
  74.       }
  75.     abort2();
  76.   }
  77.  
  78. /* =============================>>> ABORT2 <<<============================= */
  79.   abort2()
  80.   {
  81.     clobak();
  82.     tvclr();
  83.  
  84.     if (!newfil)
  85.     fclose(infile);
  86.     if (!rdonly)
  87.     fclose(outfile);
  88.  
  89.     if (strcmp(orig_file,source_file) != 0)
  90.       {
  91.     prompt("File begin used, intermediate edits in: ");
  92.     remark(source_file);
  93.       }
  94.     unlink(work_file);        /* delete the work file */
  95.  
  96.     reset();
  97.     quit();
  98.   }
  99.  
  100. /* =============================>>> FBEG   <<<============================= */
  101.   int fbeg()
  102.   { /* fbeg - go back to file top */
  103.  
  104.     SLOW int fbegv;
  105.  
  106.     if (rdonly)
  107.       {
  108.     tverrb("Can't: R/O");    /* can't do this for read only access */
  109.     return (FALSE);
  110.       }
  111.  
  112.     for (wtpage(1) ; rdpage() ; wtpage(1) )    /* write out rest */
  113.     ;
  114.  
  115.     if ((! newfil))
  116.       {
  117.     fclose(infile);            /* close source_file */
  118.       }
  119.     if (usecz)
  120.     fputc(ENDFILE,outfile);
  121.  
  122.     fclose(outfile);            /* close work_file */
  123.  
  124. /* files closed now, re-open */ 
  125.  
  126.     newfil = FALSE;        /* not a new file any more */
  127.  
  128.     strcpy(source_file,work_file);    /* new source file */
  129.     temp_name(work_file,FALSE);        /* make a new temporary name */
  130.  
  131.     if (!(infile = fopen(source_file,FILEREAD)))
  132.     goto l900;
  133.     else
  134.     ineof = FALSE;
  135.  
  136.     unlink(work_file);            /* get rid of previous copies */
  137.     if (!(outfile = fopen(work_file,FILEWRITE)))
  138.       {
  139.     goto l900;
  140.       }
  141.  
  142.     fbegv=rdpage();        /* read in new buffer */
  143.     newscr();
  144.     return (fbegv);
  145.  
  146. l900: tverrb("Error re-opening");
  147.     return (FALSE);
  148.   }
  149.  
  150. /* =============================>>> FILE_EXIT <<<============================= */
  151.   file_exit()
  152.   { /* close the input and output files, rename */
  153.  
  154.     SLOW int i;
  155.  
  156.     if (!newfil)        /* don't close input if new file */
  157.       {
  158.     fclose(infile);
  159.       }
  160.  
  161.     while (!rdonly && !*dest_file)
  162.       {
  163.     remark("No name for output file has been specified.");
  164.         prompt("Enter new name for output file: ");
  165.     reply(dest_file,FNAMESIZE);
  166.       }
  167.  
  168.     if (!rdonly)    /* don't close output if read only access */
  169.       {
  170.     if (usecz)
  171.         fputc(ENDFILE,outfile);
  172.     set_mode(outfile);        /* set output mode if can */
  173.     fclose(outfile);
  174.  
  175.     /*    orig_file has the name to be renamed to .bak
  176.     work_file has the file name we want to be dest_name
  177.     */
  178.     if (strcmp(orig_file,dest_file) == 0)    /* make backup version */
  179.       {
  180.         strcpy(stemp,orig_file);
  181. #ifndef COMMA_BAK
  182.         if ((i = rindex(stemp,FILESEP)) > 0)    /* see if extenstion */
  183.         scopy(BACKEXT,0,stemp,i);        /* make .bak */
  184.         else
  185.           {
  186.         scopy(BACKEXT,0,stemp,strlen(stemp));    /* just add on */
  187.           }
  188. #else
  189.         i = rindex(orig_file,'/')+1;
  190.         scopy(".,",0,stemp,i);
  191.         scopy(orig_file,i,stemp,strlen(stemp));
  192. #endif
  193.  
  194.         unlink(stemp);            /* delete previous generation */
  195.         ren_file(orig_file,stemp);        /* rename the file */
  196.         if (!makebackup)            /* don't want to keep old one */
  197.         unlink(stemp);    /* delete it if don't want backup file */
  198.       }
  199.  
  200.     if (strcmp(orig_file,source_file) != 0)    /* delete intermediate file */
  201.         unlink(source_file);
  202.  
  203.  
  204.     while (infile = fopen(dest_file,FILEREAD))    /* output exists? */
  205.       {
  206.         fclose(infile);
  207.         prompt("Output file "); prompt(dest_file);
  208.         prompt(" already exists.  Overwrite it? (y/n) ");
  209.         ureply(stemp,1);
  210.         if (*stemp == 'Y')
  211.           {
  212.         unlink(dest_file);
  213.         break;
  214.           }
  215.         prompt("Enter new name for output file: ");
  216.         reply(dest_file,FNAMESIZE);
  217.       }
  218.  
  219.     ren_file(work_file,dest_file);        /* finally, rename last file */
  220.       }
  221.  
  222.   }
  223.  
  224. /* =============================>>> FOPENX  <<<============================= */
  225.   fopenx(argc,argv)
  226.   int argc;
  227.   char *argv[];
  228.   {  /* open the input file
  229.     This routine picks up file name from the user, creates a backup
  230.     version in some appropriate manner, and opens the file for input
  231.     and output. */
  232.  
  233.     SLOW int iswval, iswbeg, argnum, set_ttymode;
  234.     SLOW char ch;
  235.     char rply[4];
  236.  
  237.     usebak = logdef;        /* if useing backup log file */
  238.  
  239.     ttymode = FALSE;        /* not in tty mode, so io ok */
  240.     ttynext = 1000;        /* force read */
  241.  
  242.     if (argc <= 1)
  243.       {
  244.     remark("Usage: tvx filename [-b -i -l -o=f -r -s -t -w -# {-z -c=f}]");
  245. #ifdef FULLHELP
  246.     remark("");
  247.     prompt(" Options: "); remark(VERSION);
  248.     remark("  -[no]b : backup file   -[no]i : autoindent");
  249.     remark("  -[no]l : make command log file");
  250.     remark("  -o=outputfile          -r : read only");
  251.     remark("  -s : big save buff     -[no]w : word processing mode");
  252.     remark("  -t : tty edit mode     -# : set virtual window lines to #");
  253. #ifdef MSDOS
  254.         remark("  -[no]z : use control-z for end of file");
  255. #endif
  256. #ifdef CONFIGFILE
  257. #ifdef MSDOS
  258.         remark("  -c=configfile        -c : use /bin/config.tvx");
  259. #endif
  260. #ifdef GEMDOS
  261.         remark("  -c=configfile        -c : use /bin/config.tvx");
  262. #endif
  263. #ifdef OSCPM
  264.         remark("  -c=configfile        -c : use A:config.tvx");
  265. #endif
  266. #endif
  267. #ifdef UNIX
  268.     remark("  {options not available for unix}");
  269. #endif
  270. #endif
  271.     remark("");
  272.     reset();
  273.     quit();
  274.       }
  275.  
  276.     newfil=                /* assume opening an old file */
  277.     rdonly = FALSE;            /* assume not read only */
  278.     makebackup = MAKE_BACKUP;        /* default value for make a backup */
  279.     blimit = BUFFLIMIT;
  280.  
  281.     for (argnum = 1 ; argnum < argc ; ++argnum)
  282.       {
  283.     strcpy(stemp,argv[argnum]);    /* pick up the file name or switch */
  284. REDO:
  285.     if (stemp[0] == SWITCH)        /* switch in form "/R filename" only */
  286.       {
  287.         iswbeg=1;        /* start at 1 */
  288.         iswval = TRUE;
  289.         if (clower(stemp[1]) == 'n' && clower(stemp[2]) == 'o')
  290.           {
  291.         iswval = FALSE ; iswbeg = 3 ;
  292.           }
  293.  
  294.         ch = clower(stemp[iswbeg]);        /* get the char */
  295.         if (ch == 'r')        /* read only access */
  296.         rdonly=iswval;
  297.         else if (ch == 'i')        /* auto indent */
  298.         autoin = iswval;
  299.         else if (ch == 'w')        /* word processing mode */
  300.           {
  301.         if (iswval)
  302.             wraplm = 70;
  303.         else
  304.             wraplm = 0;
  305.           }
  306.         else if (ch == 'l')
  307.         usebak=iswval;
  308.         else if (ch == 'b')
  309.         makebackup = iswval;    /* make a backup file */
  310.         else if (ch == 'z')
  311.         usecz = iswval;
  312.         else if (ch == 'o' && (stemp[iswbeg+1] == '=' ||
  313.           stemp[iswbeg+1] == ':'))    /* specifying output */
  314.           {
  315.         if (!iswval)        /* wrong order! */
  316.           {
  317.             remark("Bad -O= switch");
  318.             quit();
  319.           }
  320.         scopy(stemp,iswbeg+2,dest_file,0);  /* remember name */
  321.           }
  322. #ifdef CONFIGFILE
  323.         else if (stemp[iswbeg] == 'c' && stemp[iswbeg+1] == 0) /* default cfg */
  324.           {
  325.         strcpy(stemp,cfgname);
  326.           goto REDO;
  327.           }
  328.         else if (stemp[iswbeg] == 'c' && (stemp[iswbeg+1] == '=' ||
  329.           stemp[iswbeg+1] == ':'))    /* specifying config */
  330.           {
  331.         expand_name(&stemp[iswbeg+2]);
  332.         if ((bkuin = fopen(&stemp[iswbeg+2],FILEREAD))==0)
  333.           {
  334.             remark("Can't open configuration file.");
  335.             continue;
  336.           }
  337.         rdcfg(lexsym,LEXVALUES+1);
  338.         rdcfg(synofr,20);
  339.         rdcfg(synoto,20);
  340.         rdcfg(funchar,50);
  341.         rdcfg(funcmd,50);
  342.         rdcfg(&funkey,1);
  343.         rdcfg(&autoin,1);
  344.         rdcfg(&ddline,1);
  345.         rdcfg(&dscrl,1);
  346.         rdcfg(&dxcase,1);
  347.         rdcfg(&wraplm,1);
  348.         rdcfg(&use_wild,1);
  349.         rdcfg(&usebak,1);
  350.         logdef = usebak;
  351. #ifdef MSDOS
  352.         rdcfg(&usecz,1);
  353. #endif
  354. #ifdef GEMDOS
  355.         rdcfg(&usecz,1);
  356. #endif
  357.         fclose(bkuin);
  358.           }
  359. #endif
  360.         else if (ch == 's')    /* big save buffer */
  361.           {
  362.         if (!iswval)
  363.             blimit=BUFFLIMIT;
  364.         else
  365.             blimit=BUFFLIMIT*3;
  366.           }
  367. #ifndef VTERM
  368.         else if (ch == 't')    /* tty mode */
  369.         set_ttymode = iswval;    /* make a backup file */
  370. #endif
  371.         else if (ch >= '0' && ch <= '9')    /* making a virtual window */
  372.           {
  373.         tvlins = atoi(&stemp[iswbeg]);    /* get virtual screen size */
  374.         if (tvlins < 3 || tvlins > tvhardlines)    /* invalid window */
  375.           {
  376.             remark("Invalid window size");
  377.             tvlins = tvhardlines;
  378.           }
  379.         else
  380.           {
  381.             ddline = (tvlins / 2) + 1;    /* fix home line */
  382.             setdscrl();
  383.           }
  384.           }
  385.         else                /* illegal switch */
  386.           {
  387.         prompt("Unknown switch -"); ttwt(ch);
  388.         prompt(": Ignore and continue? (y/n) ");
  389.         ureply(rply,1);
  390.         if (*rply != 'Y')
  391.           {
  392.             reset();  quit();
  393.           }
  394.           }
  395.       }
  396.     else            /* must have a file name */
  397.       {
  398.         strcpy(orig_file,stemp);
  399.       }
  400.       }        /* end for */
  401.  
  402. /*    now open file properly - make copies to all 4 names */
  403.  
  404. GETNAME:
  405.     while (!*orig_file)
  406.       {
  407.         ask("Edit file? ",orig_file,FNAMESIZE);
  408.       }
  409.  
  410.     expand_name(orig_file);        /* expand on unix */
  411.  
  412.     if (!(infile = fopen(orig_file,FILEREAD)))    /* can open? */
  413.       {
  414.         prompt("Create file "); prompt(orig_file);
  415.         prompt("? (y/n) ");
  416.         ureply(rply,1);
  417.         if (*rply != 'Y')
  418.           {
  419.         *orig_file = 0; goto GETNAME;
  420.           }
  421.         if (*dest_file)
  422.             remark("New file, -o= switch ignored");
  423.         *dest_file = 0;
  424.         newfil = TRUE;        /* a new file */
  425.         rdonly = FALSE;
  426.       }
  427.  
  428. /* orig_file now has the name of the source file, and it might be open */
  429.  
  430.     ineof = FALSE;
  431.     strcpy(source_file,orig_file);    /* copy to other names */
  432.     strcpy(work_file,orig_file);
  433.     if (!*dest_file)        /* no -o specified */
  434.         strcpy(dest_file,orig_file);
  435.  
  436.  
  437.     if (!newfil)            /* not new file */
  438.       {
  439.         fclose(infile);        /* close orig file */
  440.         if (!(infile = fopen(source_file,FILEREAD)))    /* re-open */
  441.           {
  442.         remark("Internal editor error, aborting");
  443.         exit(100);
  444.           }
  445.         get_mode(infile);        /* get mode of original file */
  446.       }
  447.     else
  448.       {
  449.         *orig_file = *source_file = 0; 
  450.       }
  451.  
  452. /* now see if we can make an output file */
  453.     
  454.     if (!rdonly)
  455.       {
  456.         temp_name(work_file,TRUE);    /* make into a temporary name 1st time*/
  457.         unlink(work_file);        /* get rid if already there */
  458.  
  459.         if (!(outfile = fopen(work_file,FILEWRITE)))
  460.           {
  461.         prompt("Unable to create output work file: ");
  462.         remark(work_file);
  463.         if (!newfil)
  464.           {
  465.                 prompt("Continue in read only mode? (y/n) ");
  466.             ureply(rply,1);
  467.             if (*rply != 'Y')
  468.               {
  469.             fclose(infile);
  470.             reset();
  471.             exit(100);        /* abnormal exit */
  472.               }
  473.           }
  474.             *dest_file = *work_file = 0;
  475.         rdonly = TRUE;
  476.           }
  477.       }
  478.     else
  479.       {
  480.         *dest_file = *work_file = 0;
  481.       }
  482.  
  483.     ttymode = force_tty ? TRUE : set_ttymode;    /* now safe to set ttymode */
  484.   }
  485.  
  486. /* =============================>>> setdscrl <<<============================= */
  487.   setdscrl()
  488.   {    /* compute a new value for dscrl */
  489.  
  490.     if (dscrl == 0)
  491.     return;            /* if already 0, don't change */
  492.     dscrl = tvlins / 3;
  493.     if ((ddline + dscrl) >= tvlins)    /* looks ugly if hits last line */
  494.     dscrl--;
  495.     if (dscrl < 0)        /* don't allow this */
  496.     dscrl = 0;
  497.   }
  498.  
  499. #ifdef CONFIGFILE
  500. /* =============================>>> RDCFG <<<============================= */
  501.   rdcfg(toset,cnt)
  502.   char *toset;
  503.   int cnt;
  504.     {    /* read cnt vals from bkuin */
  505.  
  506.     FAST int i,val;
  507.  
  508.     for (i = 0 ; i < cnt ; ++i)
  509.       {
  510.     if ((val = fgetc(bkuin)) == EOF)
  511.      {
  512.         remark("Invalid configuration file, aborting");
  513.         fclose(bkuin);
  514.         quit();
  515.      }
  516.     *toset++ = val;    /* replace with new commands */
  517.       }
  518.   }
  519. #endif
  520.  
  521. /* =============================>>> ADDFIL <<<============================= */
  522.   int addfil(rw)
  523.   int rw;
  524.   {  /* addfil - add contents of external file to save buffer
  525.     positive means read into buffer, negative means write save buffer */
  526.  
  527.     SLOW int chr;
  528.     SLOW int limit;
  529.  
  530.     SLOW BUFFINDEX fromch;
  531.     SLOW int i;
  532.     SLOW FILE *outf;
  533.  
  534.     if (rw >= 0)    /* read a file */
  535.       {
  536.     if (!gbgcol(nxtchr))    /* gc first */
  537.       {
  538.         newscr();
  539.         tverrb("No save room");
  540.         return (FALSE);
  541.       }
  542.  
  543.         tvclr();
  544. #ifdef LASL
  545.     ask("Read external filename: ",stemp,FNAMESIZE);
  546. #else
  547.     ask("Yank filename: ",stemp,FNAMESIZE);
  548. #endif
  549.  
  550.     expand_name(stemp);            /* expand on some systems */
  551.  
  552.     if (!(bkuin = fopen(stemp,FILEREAD)) || !*stemp)
  553.       {
  554.         newscr();
  555. #ifdef LASL
  556.         tverrb(" Unable to open external file ");
  557. #else
  558.         tverrb(" Unable to open yank file ");
  559. #endif
  560.         return (FALSE);
  561.      }
  562.  
  563.     savlin=0 ; savlen=0 ; nxtsav =mxbuff ;    /* clear out save buffer */
  564.  
  565.     limit = max(nxtchr,mxbuff/2)-ALMOSTOUT;
  566.     do
  567.       {
  568.         if ((chr = getchr(bkuin)) < 0)
  569.           {
  570.         newscr();
  571.         fclose(bkuin);
  572.         return (TRUE);
  573.           }
  574.         if (chr == NEWLINE)
  575.           {
  576. #ifdef FILELF
  577.             getchr(bkuin);
  578. #endif
  579.         chr=ENDLINE;
  580.         ++savlin;
  581.           }
  582.         *(buff+nxtsav--) = chr;
  583.         if (nxtsav <= limit)
  584.           {
  585.         newscr();
  586.         tverrb("File only partly read");
  587.         break;
  588.           }
  589.       }
  590.     while (1);
  591.     fclose(bkuin);
  592.     return (TRUE);
  593.       }
  594.  
  595.     /* --------------- to here, then writing from save buffer --------------*/
  596.  
  597.  
  598.     if (nxtsav==mxbuff)        /* nothing to save */
  599.       {
  600.      tverrb("Save buffer empty!");
  601.     return (TRUE);
  602.       }
  603.  
  604.     tvclr();
  605.     ask("Write to external filename: ",stemp,FNAMESIZE);
  606.  
  607.     expand_name(stemp);            /* expand on some systems */
  608.  
  609.     if (!(outf = fopen(stemp,FILEWRITE)) || !*stemp)
  610.       {
  611.     newscr();
  612.     tverrb(" Unable to open external file ");
  613.     return (FALSE);
  614.       }
  615.  
  616.     
  617. /*   # move down line to make space for new */
  618.     fromch = mxbuff;        /* where taking saved stuff from */
  619.     for (i = 0 ; i < savlin ; ++i)
  620.       {
  621.         for ( ; ; )        /* scan save buffer */
  622.       {
  623.          if ((chr = *(buff+fromch--)) == ENDLINE)
  624.           {
  625.         fputc(NEWLINE,outf);
  626. #ifdef FILELF
  627.         fputc(LF,outf);
  628. #endif
  629.         break;
  630.           }
  631.         else
  632.         fputc(chr,outf);
  633.       }
  634.       }
  635.  
  636.     if (usecz)
  637.     fputc(ENDFILE,outf);
  638.     fclose(outf);
  639.     newscr();
  640.     return (TRUE);
  641.  
  642.   }
  643.  
  644. /*=============================>>> SCOPY  <<<================================*/
  645.   scopy(old,oldbeg,new,newbeg)
  646.   char old[], new[];
  647.   int oldbeg,newbeg;
  648.   {
  649.     while (old[oldbeg])
  650.     new[newbeg++]=old[oldbeg++];
  651.     new[newbeg] = 0;
  652.   }
  653.  
  654. /* **************************************************************************
  655.  
  656.     Following code is for non-unix systems
  657.  
  658.  **************************************************************************** */
  659. #ifndef UNIX
  660. /* =============================>>> get_mode <<<============================= */
  661.   get_mode(f)
  662.   FILE *f;
  663.   {        /* gets access mode of open file f */
  664.   }
  665.  
  666. /* =============================>>> set_mode <<<============================= */
  667.   set_mode(f)
  668.   FILE *f;
  669.   {        /* sets access mode of open file f */
  670.   }
  671.  
  672. /* ==========================>>> expand_name <<<============================ */
  673.   expand_name(n)
  674.   char *n;
  675.   {        /* expands unix file names */
  676.   }
  677.  
  678. /* =============================>>> ren_file <<<=========================== */
  679.   ren_file(old,new)
  680.   char *old, *new;
  681.   {
  682. #ifndef GEMDOS
  683.     if (rename(old,new) != 0)
  684.       {
  685.     prompt(old) ; prompt(" not renamed to "); remark(new);
  686.       }
  687. #endif
  688. #ifdef GEMDOS
  689.     gemdos(0x56,0,old,new);    /* can't find C version */
  690. #endif
  691.   }
  692.  
  693. /* =============================>>> temp_name <<<=========================== */
  694.   temp_name(n,first)
  695.   char *n;
  696.   int first;
  697.   {
  698.     /* generates a temporary name from n.  Depending on value of
  699.        first, it will either add a 1 or 2 to name */
  700.  
  701.     SLOW int i;
  702.  
  703.     if (first)
  704.       {
  705.     if ((i = rindex(n,FILESEP)) > 0)    /* see if extenstion */
  706.         scopy(TEMPEXT,0,n,i);        /* make .bak */
  707.     else
  708.       {
  709.         scopy(TEMPEXT,0,n,strlen(n));    /* just add on */
  710.       }
  711.       }
  712.     else
  713.       {
  714.     i = strlen(n);
  715.     if (n[i-1] == '1')
  716.         n[i-1] = '2';
  717.     else
  718.         n[i-1] = '1';
  719.       }
  720.   }
  721.  
  722. #endif
  723.  
  724. /* **************************************************************************
  725.  
  726.     This section is for the version supporting command logfile
  727.     backup.  The code necessary for this version is included here,
  728.     and may be compiled by defining VB to be a blank.
  729.  
  730.  **************************************************************************** */
  731.  
  732. /* =============================>>> OPNBAK <<<============================= */
  733.   opnbak()
  734.   { 
  735.     /* opnbak - open the backup log file
  736.        if VB defined as ' ', then backup version created */
  737.  
  738. #ifdef VB
  739.  
  740.     if (! usebak)
  741.       {
  742.     bakflg = FALSE;
  743.     return;
  744.       }
  745.  
  746.     bkuout = fopen(BACKUPNAME,FILEWRITE);
  747.     bakpos = 1;
  748. #endif
  749.  
  750.   }
  751.  
  752. /* =============================>>> PUTBAK <<<============================= */
  753.   putbak(chr)
  754.   char chr;
  755.   { /* putbak - put a character into the backup file */
  756.  
  757. #ifdef VB
  758.     static char copy;
  759.  
  760.     if (! usebak)
  761.     return;
  762.     copy=chr;
  763.     if (copy < 32 || copy == '@' || copy==delkey)
  764.       {
  765.     fputc('@',bkuout);
  766.     bakcrlf();
  767.     if (copy < 32)
  768.         copy += '@';
  769.     else if (copy==delkey)
  770.         copy = '?';     /* let @? be rubout */
  771.       }
  772.     fputc(copy,bkuout);
  773.     bakcrlf();
  774. #endif
  775.   }
  776.  
  777. #ifdef VB
  778. /* =============================>>> BAKCRLF <<<============================= */
  779.   bakcrlf()
  780.   {    /* conditionally put a cr/lf to backup file */
  781.  
  782.     if (++bakpos > 63)
  783.       {
  784.     fputc(NEWLINE,bkuout);
  785. #ifdef FILELF
  786.     fputc(LF,bkuout);
  787. #endif
  788.     bakpos = 1;
  789.       }
  790.   }
  791. #endif
  792.  
  793. /* =============================>>> CLOBAK <<<============================= */
  794.   clobak()
  795.   {
  796.  
  797. #ifdef VB
  798.     if (! usebak)
  799.     return;
  800.     fputc(NEWLINE,bkuout);
  801. #ifdef FILELF
  802.     fputc(LF,bkuout);
  803. #endif
  804.     if (usecz)
  805.     fputc(ENDFILE,bkuout);
  806.  
  807.     fclose(bkuout);
  808. #endif
  809.   }
  810.  
  811. /* =============================>>> GETBAK <<<============================= */
  812.   getbak(chr)
  813.   char *chr;
  814.   {  /* get one char from back up file if there */
  815.  
  816. #ifdef VB
  817.     SLOW int ich;
  818.  
  819. l10:
  820.     if ((ich = getchr(bkuin)) < 0 || ich == ENDFILE)
  821.       {
  822. l15:    fclose(bkuin);
  823.     *chr=0;            /* harmless character */
  824.     bakflg=FALSE;
  825.     newscr();
  826.     return;
  827.       }
  828.     if (ich == NEWLINE)
  829.     goto l10;
  830. #ifdef FILELF
  831.     if (ich == LF)
  832.     goto l10;
  833. #endif
  834.     *chr=ich;
  835.     if (ich=='@')
  836.       {
  837. l20:    if ((ich = getchr(bkuin)) < 0 || ich == ENDFILE)
  838.       {
  839.         goto l15;
  840.       }
  841.     if (ich == NEWLINE)
  842.         goto l20;
  843. #ifdef FILELF
  844.     if (ich == LF)
  845.         goto l20;
  846. #endif
  847.     *chr=ich;
  848.     if (ich == '?')
  849.         *chr=delkey;
  850.     else if (*chr != '@')
  851.         *chr= ich - '@';
  852.       }
  853. #endif
  854.   }
  855.  
  856. /* =============================>>> OPNATF <<<============================= */
  857.   opnatf()
  858.   { /* open an indirect command file */
  859.  
  860. #ifdef VB
  861.  
  862.  
  863.     tvclr();
  864.  
  865.     ask("Name of command file: ",stemp,FNAMESIZE);
  866.         /* read in the file name from the terminal */
  867.  
  868.     expand_name(stemp);
  869.  
  870.     if (!*stemp)
  871.     return;
  872.  
  873.     if (!(bkuin = fopen(stemp,FILEREAD)))
  874.       {
  875.     newscr();
  876.     tverrb("Bad @ name");
  877.     return;
  878.       }
  879.     bakflg=TRUE;
  880.     newscr();
  881. #endif
  882.   }
  883.  
  884. /* **************************************************************************
  885.  
  886.     This section contains code to write and read buffers of data
  887.  
  888.  **************************************************************************** */
  889.  
  890. /* =============================>>> RDPAGE <<<============================= */
  891.   int rdpage()
  892.   { /* rdpage - read in file up to buffer limit
  893.        only place text read from edited file */
  894.  
  895.     SLOW int chr;
  896.     SLOW int l,newlns;
  897.  
  898.     if (newfil)        /* can't read in when a new file */
  899.       {
  900.     return (FALSE);
  901.       }
  902.     if (nxtlin > mxline || nxtchr > mxbuff-130)    /* error check */
  903.       {
  904.     tverrb("Lines filled ");
  905.     return (FALSE);
  906.       }
  907.  
  908.     newlns=0;            /* begin at the beginning */
  909.     while (mxline-nxtlin > LINELIMIT  && nxtsav-nxtchr > blimit && !ineof)
  910.       {             /* read in while have room */
  911.     chr = fgetc(infile);
  912.     if (chr == EOF)
  913.       {
  914.         ineof = TRUE;
  915.         break;
  916.       }
  917.     if (chr == ENDFILE && usecz)
  918.       {
  919.         ineof = TRUE;
  920.         break;
  921.       }
  922. #ifdef FILELF
  923.     if (chr == LF)
  924.         continue;
  925. #endif
  926.     *(buff+nxtchr) = BEGLINE;
  927.     *(lines+nxtlin) = nxtchr++;
  928.     ++newlns ;
  929.         
  930.     while (chr != NEWLINE)        /* store a line */
  931.       {
  932.         *(buff+nxtchr++) = chr;
  933.         chr = fgetc(infile);
  934.         if (chr == EOF)
  935.           {
  936.         ineof = TRUE;
  937.         break;
  938.           }
  939.         if (chr == ENDFILE && usecz)
  940.           {
  941.         ineof = TRUE;
  942.         break;
  943.           }
  944.       }
  945.     *(buff+nxtchr++)=ENDLINE;
  946.     ++nxtlin;
  947.       }
  948.  
  949. l900:
  950.     if (nxtlin > 1)        /* we really read something */
  951.       {
  952.     curlin=1;        /* point to top of char */
  953.     curchr = *(lines+1)+1;    /* point to first character */
  954.       }
  955.     return (newlns > 0) ;
  956.   }
  957.  
  958. /* =============================>>> WTPAGE <<<============================= */
  959.   wtpage(whow)
  960.   int whow;
  961.   { /* wtpage - write out contents of text buffer, and clear line list */
  962.  
  963.     FAST int i;
  964.     FAST char *chrp;
  965.     SLOW char *lim;
  966.     SLOW int wlimit;
  967.  
  968.     if (whow < 0)        /* allow writing partial buffer */
  969.     wlimit = curlin - 1;
  970.     else
  971.     wlimit = nxtlin -1;
  972.  
  973.     if (nxtlin <= 1 || rdonly)
  974.       {
  975.     tverr("Empty buffer");
  976.     goto zapb;
  977.       }
  978.  
  979.     if (whow < 0)
  980.     tverr("Writing partial buffer");
  981.     else
  982.     tverr("Writing buffer");
  983.  
  984.     tvhdln();
  985.  
  986.     for (i = 1 ; i <= wlimit ; ++i)
  987.       {
  988.     chrp = buff + (*(lines+i)+1);    /* ptr to first char of line */
  989.     while (*chrp != ENDLINE)
  990.       {
  991.         fputc(*chrp++, outfile);
  992.       }
  993.     fputc(NEWLINE,outfile);
  994. #ifdef FILELF
  995.     fputc(LF,outfile);
  996. #endif
  997.       }
  998.  
  999. zapb:
  1000.  
  1001.     if (whow < 0)
  1002.       {
  1003.     killin(-(curlin-1));    /* kill to top of buffer */
  1004.     if (!gbgcol(nxtchr))    /* gc first */
  1005.       {
  1006.         newscr();
  1007.         tverrb("Warning: no extra room created");
  1008.         return (FALSE);
  1009.       }
  1010.     return (TRUE);
  1011.       }
  1012.     else
  1013.       {
  1014.     lim = buff + nxtsav;
  1015.     for (chrp=buff ; chrp < lim ; *chrp++ = GARBAGE)
  1016.         ;
  1017.     tvdlin =            /* start on first line again */
  1018.     nxtlin =            /* reset to initial state */
  1019.     nxtchr = 1;
  1020.     curchr =
  1021.     curlin=0;
  1022.     return (TRUE);
  1023.       }
  1024.   }
  1025.  
  1026. /* **************************************************************************
  1027.  
  1028.     This section contains misc. stuff likely to be operating system dependent
  1029.  
  1030.  **************************************************************************** */
  1031.  
  1032. /* ===========================>>> OPSYSTEM <<<============================== */
  1033.   opsystem()
  1034.   {
  1035. #ifdef MSDOS            /* !!! cii-86 dependent */
  1036.  
  1037.     char rp[80];
  1038.  
  1039. MS_AGAIN:
  1040.     tvclr();
  1041.     ask("DOS command (any key to resume edit when done): ",rp,79);
  1042.     remark("");
  1043.     if (system(rp) != 0)
  1044.       {
  1045.         tvxy(1,1);
  1046.     ask("Sorry, but couldn't find COMMAND.COM.",rp,1);
  1047.       }
  1048.     else
  1049.       {
  1050.     tvxy(1,1);
  1051.     ask("",rp,1);
  1052.     if (*rp == '!')
  1053.        goto MS_AGAIN;
  1054.       }
  1055.     verify(1);
  1056. #endif
  1057. #ifdef UNIX
  1058.     unix_sys();
  1059. #endif
  1060. #ifdef GEMDOS
  1061.     return;
  1062. #endif
  1063.   }
  1064.  
  1065. #ifndef UNIX
  1066. /* ===========================>>> TTINIT <<<============================== */
  1067.   ttinit()
  1068.   { /*  this routine could be used to set up keyboard input, perhaps
  1069.     turning on non-echoed input */
  1070.     return;
  1071.   }
  1072.  
  1073. /* ===========================>>> TTCLOS <<<============================== */
  1074.   ttclos()
  1075.   {  /* this routine could undo anything ttinit() did */
  1076.     return;
  1077.   }
  1078. #endif
  1079.  
  1080. #ifndef VTERM
  1081. /* ===========================>>> TTRD <<<============================== */
  1082.   ttrd()
  1083.   { /* this routine is called to read one unechoed char from the keyboard */
  1084.  
  1085.   static int tc, i;
  1086.   static char chr;
  1087.  
  1088. RDTOP:
  1089.     if (ttymode)
  1090.     tc = rdtty();        /* get a char from the tty */
  1091.     else
  1092.       {
  1093.  
  1094. #ifdef CPM
  1095.     while (!(tc = bdos(6,-1)))        /* cp/m implementation */
  1096.     ;
  1097. #endif
  1098. #ifdef MSDOS
  1099.     tc = bdos(7,-1);        /* ms-dos implementation  (!!! cii-86) */
  1100. #endif
  1101. #ifdef GEMDOS
  1102.     tc = gemdos(7);        /* GEMDOS application */
  1103. #endif
  1104. #ifdef UNIX
  1105.     tc = ttrd_unix();
  1106. #endif
  1107.        }
  1108.  
  1109.     chr = tc & 0377;
  1110.  
  1111.     if (chr == funkey)            /* function key */
  1112.       {
  1113.     if (ttymode)
  1114.       {
  1115.         tc = rdtty();        /* get a char from the tty */
  1116.       }
  1117.     else
  1118.       {
  1119. #ifdef CPM
  1120.     while (!(tc = bdos(6,-1)))        /* cp/m implementation */
  1121.         ;
  1122. #endif
  1123. #ifdef MSDOS
  1124.     tc = bdos(7,-1);        /* ms-dos implementation */
  1125. #endif
  1126. #ifdef GEMDOS
  1127.     tc = gemdos(7);        /* GEMDOS application */
  1128. #endif
  1129. #ifdef UNIX
  1130.     tc = ttrd_unix();
  1131. #endif
  1132.       }
  1133.     chr = tc & 0377;
  1134.     for (i = 0 ; i < 50 && funchar[i] ; ++i)
  1135.       {
  1136.         if (chr == funchar[i])
  1137.           {
  1138.         tc = funcmd[i] & 0377;
  1139.         return (tc);
  1140.           }
  1141.       }
  1142.     goto RDTOP;            /* ignore invalid function keys */
  1143.       }
  1144.     tc = chr & 0377;
  1145.     return (tc);
  1146.  
  1147.   }
  1148. #endif
  1149.  
  1150. #ifndef UNIX
  1151. /* ===========================>>> TTWT <<<============================== */
  1152.   ttwt(chr)
  1153.   char chr;
  1154.   { /*  this routine is called to write one char to the keyboard
  1155.     It also interprets print direction */
  1156.  
  1157.     if (ttymode)
  1158.     return;
  1159.     dispch(chr);    /* cp/m, ms-dos version */
  1160.     if (useprint)
  1161.     printc(chr);
  1162.   }
  1163. #endif
  1164.  
  1165. #ifdef MSDOS
  1166. /* ===========================>>> GETCHR <<<============================== */
  1167.   getchr(filnum)
  1168.   FILE *filnum;
  1169.   {  /* get a character from filnum */
  1170.  
  1171. #define EOFBYTE 26
  1172.  
  1173.     FAST int ichr;
  1174.  
  1175.     if (((ichr = fgetc(filnum)) == EOFBYTE))
  1176.       {
  1177.     if (usecz)
  1178.         return (EOF);
  1179.       }
  1180.  
  1181.     return (ichr);
  1182.   }
  1183. #endif
  1184.  
  1185. #ifdef GEMDOS
  1186. /* ===========================>>> GETCHR <<<============================== */
  1187.   getchr(filnum)
  1188.   FILE *filnum;
  1189.   {  /* get a character from filnum */
  1190.  
  1191. #define EOFBYTE 26
  1192.  
  1193.     FAST int ichr;
  1194.  
  1195.     if (((ichr = fgetc(filnum)) == EOFBYTE))
  1196.       {
  1197.     if (usecz)
  1198.         return (EOF);
  1199.       }
  1200.  
  1201.     return (ichr);
  1202.   }
  1203. #endif
  1204.  
  1205. /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1206.  
  1207.     TVX TERMINAL DRIVER  for various terminals
  1208.  
  1209.    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  1210.  
  1211.  
  1212. /* =============================>>> TRMINI <<<============================= */
  1213.   trmini()
  1214.   {  /* initialize term if necessary */
  1215.  
  1216.     sendcs(cinit);
  1217.     tvclr();
  1218.   }
  1219.  
  1220. /* =============================>>> reset <<<============================= */
  1221.   reset()
  1222.   {
  1223.     sendcs(cendit);
  1224.     ttclos();
  1225.   }
  1226.  
  1227. /* =============================>>> ttyverify <<<============================= */
  1228.   ttyverify(knt)
  1229.   int knt;
  1230.   {
  1231.     SLOW BUFFINDEX oldline, oldchr, limit;        /* current position */
  1232.  
  1233.     oldline = curlin; oldchr = curchr;    /* remember where we were */
  1234.  
  1235.     ttymode = FALSE;            /* enable output stuff */
  1236.  
  1237.     if (knt < 0)            /* type some above */
  1238.       {
  1239.     curchr = 0;
  1240.     curlin = curlin + knt ;        /* back n lines */
  1241.     if (curlin < 1)
  1242.        curlin = 1;
  1243.     while (curlin < oldline)    /* write out the lines */
  1244.         ttyline(curlin++);    /* write line, no cursor */
  1245.       }
  1246.     else
  1247.       {
  1248.     ttyline(curlin);        /* type current line */
  1249.     curchr = 0;            /* this turns off cursor */
  1250.     limit = oldline + knt - 1;
  1251.     if (limit >= nxtlin)
  1252.         limit = nxtlin - 1;
  1253.     while (++curlin <= limit)
  1254.         ttyline(curlin);
  1255.       }
  1256.     curchr = oldchr;
  1257.     curlin = oldline;
  1258.     ttymode = TRUE;
  1259.   }
  1260.  
  1261. /* =============================>>> ttyline <<<============================= */
  1262.   ttyline(linenr,cursor)
  1263.   BUFFINDEX linenr;
  1264.   {
  1265.     SLOW BUFFINDEX chrc;
  1266.     SLOW int outlen;
  1267.     
  1268.     chrc = *(lines+linenr)+1;    /* point to first character in line */
  1269.     outlen = 0;            /* nothing out yet */
  1270.     for ( ; ; )
  1271.       {
  1272.     if (chrc == curchr)    /* at cursor */
  1273.       {
  1274.         outlen += 2;
  1275.         if (outlen > 78)    /* line wrap */
  1276.           {
  1277.         remark("");
  1278.         ttwt('_');
  1279.         outlen = 3;
  1280.           }
  1281.         ttwt('/'); ttwt('\\');
  1282.       }
  1283.         if (*(buff+chrc) == ENDLINE)    /* done */
  1284.         break;
  1285.     outlen += ttywtch(*(buff+chrc));    /* watch for line wrap */
  1286.     if (outlen > 78)
  1287.       {
  1288.         remark("");
  1289.         ttwt('_');
  1290.         outlen = 1;
  1291.       }
  1292.     ++chrc;            /* next character */
  1293.       }
  1294.     remark("");
  1295.   }
  1296.   
  1297. /* =============================>>> ttywtch <<<============================= */
  1298.   ttywtch(chr)
  1299.   char chr;
  1300.   {
  1301.     if (chr >= ' ')        /* regular character */
  1302.       {
  1303.         ttwt(chr);
  1304.     return 1;
  1305.       }
  1306.     else            /* control character */
  1307.       {
  1308.     ttwt('^');
  1309.     ttwt(chr+'@');
  1310.     return 2;
  1311.       }
  1312.   }
  1313.   
  1314. /* =============================>>> rdtty <<<============================= */
  1315.   rdtty(knt)
  1316.   int knt;
  1317.   {        /* fake rdtt for ttymode - only called when in ttymode */
  1318.  
  1319. #define RDBUFFSIZE 81
  1320.     static char rdtbuf[RDBUFFSIZE];
  1321.  
  1322. RDTOP:
  1323.     ttymode = FALSE;            /* take out of ttymode for echo */
  1324.     if (ttynext >= RDBUFFSIZE)        /* need to read a line */
  1325.       {
  1326.     if (ins_mode)            /* different prompts for modes */
  1327.         prompt("+");
  1328.     else
  1329.         prompt("tvx>");
  1330.     reply(rdtbuf,80);        /* read a line */
  1331.     ttynext = 0;            /* reset pointer */
  1332.       }
  1333.     ttymode = TRUE;            /* no echo again */
  1334.     if (rdtbuf[ttynext] == 0)        /* end of buffer */
  1335.       {
  1336.     ttynext = 1000;
  1337.     if (ins_mode)
  1338.         return (CR);        /* return a carriage return for ins */
  1339.     else
  1340.         goto RDTOP;            /* read another line */
  1341.       }
  1342.     else
  1343.       {
  1344.     return (rdtbuf[ttynext++]);    /* return character */
  1345.       }
  1346.   }
  1347.  
  1348. /* =============================>>> TVPLIN <<<============================= */
  1349.   tvplin(chrptr)
  1350.   BUFFINDEX chrptr;
  1351.   { /* tvplin - put line beginning at chrptr
  1352.         will only type what will fit on screen (using xout) */
  1353.  
  1354.     SLOW char tmp;
  1355.     SLOW int linlen, origx;
  1356.     SLOW BUFFINDEX i;
  1357.  
  1358. #ifdef ULBD
  1359.     SLOW int ul, bd, useul, usebd;
  1360.  
  1361.     ul = bd = useul = usebd = FALSE;
  1362. #endif
  1363.  
  1364.     last_col_out = linptr = 0;
  1365.     origx = xoutcm;            /* save x so can get true linelen */
  1366.     for (i=chrptr; *(buff+i)!=ENDLINE && xoutcm <= 240; ++i)
  1367.       {
  1368. #ifdef NO_EXTEND_CHAR
  1369.     if ((*(buff+i) < ' ' || (*(buff+i) & 0x80) ) && (*(buff+i) >= 0))
  1370.         /* control character? */
  1371. #else
  1372.     if (*(buff+i)<' ' && *(buff+i) >= 0)    /* control character? */
  1373. #endif
  1374.       {
  1375.         if (*(buff+i) == TAB)
  1376.           {
  1377.         if (tabspc > 0)
  1378.           {
  1379.             do 
  1380.               {
  1381.             linout[linptr++] = ' ';    /* replace with blanks */
  1382.             ++xoutcm;
  1383.               }
  1384.             while ( ((xoutcm-1) % tabspc) != 0);
  1385.           }
  1386.         else
  1387.           {
  1388.             linout[linptr++] = '^';
  1389.             linout[linptr++] = 'I';
  1390.             xoutcm += 2;
  1391.           }
  1392.         continue;
  1393.           }
  1394.         else        /*  other control character */
  1395.           {
  1396.         linout[linptr++] = (*(buff+i) & 0x80) ? '~' : '^';
  1397.         ++xoutcm;
  1398.         if (xoutcm==tvcols && *(buff+i) != ENDLINE)
  1399.             continue;
  1400.  
  1401. /*  #$$$    ascii machines!!!! */
  1402.         tmp = *(buff+i);
  1403.         if ((tmp &= 0x7f) < ' ')    /* ok to mix extended, ctrl */
  1404.             tmp += '@';
  1405.         linout[linptr++]=tmp;
  1406.  
  1407. #ifdef ULBD
  1408.         if ( *(buff+i)==TOGUNDERLINE && cundlb[0] != 0)
  1409.           {
  1410.             if (ul)
  1411.               {
  1412.             strcopy(cundle,0,linout,&linptr);
  1413.             ul = FALSE;
  1414.               }
  1415.             else
  1416.               {
  1417.             strcopy(cundlb,0,linout,&linptr);
  1418.             useul = TRUE;
  1419.             ul = TRUE;
  1420.               }
  1421.           }
  1422.         if (*(buff+i) == TOGBOLD && cboldb[0] != 0)
  1423.           {
  1424.             if (bd)
  1425.               {
  1426.             strcopy(cbolde,0,linout,&linptr);
  1427.             bd = FALSE;
  1428.               }
  1429.             else
  1430.               {
  1431.             strcopy(cboldb,0,linout,&linptr);
  1432.             usebd = TRUE;
  1433.             bd = TRUE;
  1434.               }
  1435.           }
  1436. #endif          
  1437.           }
  1438.       } /*# end if control character */
  1439.     else 
  1440.       {
  1441.         linout[linptr++] = *(buff+i);
  1442.       }
  1443.     ++xoutcm;
  1444.       }
  1445.  
  1446.     if (*(buff+chrptr-1)==BEGLINE)        /* write whole line */
  1447.       {
  1448.     last_col_out = linlen = min(tvcols,linptr-leftmg+1);
  1449.     if (linlen > 0)
  1450.       {
  1451.         tvlout(&linout[leftmg-1],linlen);
  1452.       }
  1453.       }
  1454.     else
  1455.       {
  1456.     linlen = min(tvcols-origx+1,linptr);
  1457.     last_col_out = linlen + origx - 1;
  1458.     if (linlen > 0)
  1459.         tvlout(linout,linlen);
  1460.       }
  1461. #ifdef ULBD
  1462.     if (useul)
  1463.     sendcs(cundle);
  1464.     if (usebd)
  1465.     sendcs(cbolde);
  1466. #endif
  1467.     
  1468.   }
  1469.  
  1470. /* =============================>>> TVLOUT <<<============================= */
  1471.   tvlout(chrbuf,lenbuf)
  1472.   char chrbuf[];
  1473.   int lenbuf;
  1474.   {  /* tvlout - intercepts tvcout calls to use line I/O */
  1475.  
  1476.     if (!(echof && !bakflg))
  1477.     return;
  1478.     ttwtln(chrbuf,lenbuf);    /* write out whole line */
  1479.   }
  1480.  
  1481. /* =============================>>> TVTYPE <<<============================= */
  1482.   tvtype(ibeg,icnt)
  1483.   int ibeg,icnt;
  1484.   { /* tytype - type icnt lines starting at lines[ibeg]
  1485.         no cr/lf on the last line */
  1486.  
  1487.     FAST int i,lim;
  1488.     SLOW BUFFINDEX start;
  1489.  
  1490.     if (!echof)
  1491.     return;
  1492.     xoutcm=tvx;
  1493.     lim = ibeg+icnt-1;
  1494.  
  1495.     for (i = ibeg ; i<=lim && i<nxtlin ; ++i)
  1496.       {
  1497.     start = (*(lines+i))+1;
  1498.     tvplin(start);    /* type out a line */
  1499.     xoutcm=1;
  1500.     if (celin[0] && last_col_out < tvcols)
  1501.         tvelin();    /* erase rest of line */
  1502.     if ( i != lim )
  1503.       {
  1504.         tvcout(CR);
  1505. #ifdef USELF
  1506.         tvcout(LF);
  1507. #endif
  1508.       }
  1509.       }
  1510.   }
  1511.  
  1512. /* =============================>>> SCRPRINT <<<============================= */
  1513.   scrprint()
  1514.   {    /* print screen on printer */
  1515.  
  1516. #ifndef UNIX
  1517.  
  1518.    SLOW beg, cnt;
  1519.  
  1520.     tvclr();        /* clear screen first */
  1521.     finddl(&beg, &cnt);
  1522.     useprint = TRUE;    /* enable printing */
  1523.     tvtype(beg,cnt);    /* and display/print */
  1524.     printc(CR);        /* force closing cr/lf */
  1525. #ifdef USELF
  1526.     printc(LF);
  1527. #endif
  1528.     useprint = FALSE;
  1529. #endif
  1530.     verify(1);        /* reset screen */
  1531.   }
  1532.  
  1533. /* =============================>>> VERIFY <<<============================= */
  1534.   verify(knt)
  1535.   int knt;
  1536.   { /* verify - rewrite the screen or type current line with cursor */
  1537.  
  1538.     SLOW int xf;
  1539.  
  1540.     if (ttymode)
  1541.     ttyverify(knt);
  1542.     else
  1543.       {
  1544.     newscr();
  1545.     xf = findx();
  1546.     tvxy(xf,tvy);    /* reset cursor to current position */
  1547.       }
  1548.   }
  1549.  
  1550. /* =============================>>> CSRCMD <<<============================= */
  1551.   csrcmd()
  1552.   {
  1553.     ins_mode = FALSE;        /* let world know in command mode */
  1554.     sendcs(ccsrcm);
  1555.   }
  1556.  
  1557. /* =============================>>> CSRINS <<<============================= */
  1558.   csrins()
  1559.   {
  1560.     SLOW int oldx,oldy,oldxot;
  1561.  
  1562.     ins_mode = TRUE;        /* in insert mode */
  1563.     sendcs(ccsrin);
  1564.  
  1565.     if (tvdlin != tvhardlines)
  1566.       {
  1567.         oldx = tvx; oldy = tvy; oldxot = xoutcm;
  1568.     tvmsg("### Insert Mode ###",FALSE);
  1569.     tvxy(oldx,oldy);
  1570.     xoutcm = oldxot;
  1571.       }
  1572.   }
  1573.   
  1574. /* **************************************************************************
  1575.  
  1576.    tv screen primitives follow
  1577.  
  1578. *************************************************************************** */
  1579.  
  1580. /* =============================>>> TVBOTB <<<============================= */
  1581.   tvbotb(n)
  1582.   int n;
  1583.   {  /* tvbotb - make n blank lines at the bottom of the screen */
  1584.  
  1585.     FAST int i,j;
  1586.  
  1587. /*  All versions  control sequences */
  1588.  
  1589.     if (n >= tvlins)
  1590.       {
  1591.     tvclr();
  1592.       }
  1593.     else 
  1594.       {
  1595.     tvxy(1,tvhardlines);    /* go to real last line */
  1596.     for (i = 1 ; i <= n ; ++i)    /* and write n blank lines */
  1597.         sendcs(cbotb);
  1598.     j=tvlins-n+1;    /* home to virtual last line */
  1599.     tvxy(1,j);    /* position at first new blank line */
  1600.       }
  1601.   }
  1602.  
  1603. /* =============================>>> TVCLR  <<<============================= */
  1604.   tvclr()
  1605.   {  /* tvclr - clear the entire screen and home */
  1606.  
  1607.     tvxy(1,1);
  1608.     tvescr();
  1609.   }
  1610.  
  1611. /* =============================>>> TVCOUT <<<============================= */
  1612.   tvcout(chr)
  1613.   char chr;
  1614.   {  /* tvcout - send one character to the terminal */
  1615.  
  1616.     if (echof && !bakflg)
  1617.     ttwt(chr);
  1618.   }
  1619.  
  1620. /* =============================>>> TVELIN <<<============================= */
  1621.   tvelin()
  1622.   {  /* tvelin - erase the rest of the current line */
  1623.  
  1624.     sendcs(celin);
  1625.   }
  1626.  
  1627. /* =============================>>> TVESCR <<<============================= */
  1628.   tvescr()
  1629.   {  /* tvescr - erase from current cursor position to end of screen */
  1630.  
  1631.     SLOW int oldx,oldy;
  1632.     FAST int i;
  1633.  
  1634.     if (cescr[0])
  1635.     sendcs(cescr);
  1636.     else
  1637.       {
  1638.     oldx = tvx ; oldy = tvy ;
  1639.     tvelin();
  1640.     for (i = oldy+1 ; i <= tvhardlines ; ++i)
  1641.       {
  1642.         tvxy(1,i);
  1643.         tvelin();
  1644.       }
  1645.     tvxy(oldx,oldy);
  1646.       }
  1647.   }
  1648.  
  1649. /* =============================>>> TVINSL <<<============================= */
  1650.   tvinsl()
  1651.   {  /* tvinsl - insert line, handle virtual screen size */
  1652.  
  1653.     SLOW int oldx,oldy;
  1654.     FAST int i;
  1655.  
  1656.     oldx = tvx ; oldy = tvy ;
  1657.     sendcs(ciline);
  1658.     if (tvlins != tvhardlines)
  1659.       {
  1660.     tvxy(1,tvlins+1);    /* kill scrolled down line */
  1661.     tvelin();
  1662.     tvxy(oldx,oldy);
  1663.       }
  1664.   }
  1665.  
  1666. /* =============================>>> TVTOPB <<<============================= */
  1667.   tvtopb(n)
  1668.   int n;
  1669.   {  /* tvtopb - create n blank lines at the top of the screen */
  1670.  
  1671.     FAST int i;
  1672.  
  1673.     if (! ctopb[0])
  1674.     return;
  1675.     tvxy(1,1);        /* home first */
  1676.     if ( n >= tvlins)
  1677.     tvescr();    /* simply erase the screen */
  1678.     else
  1679.       {
  1680.     for (i = 1 ; i <= n ; ++i)
  1681.         sendcs(ctopb);
  1682.     if (tvlins != tvhardlines)
  1683.           {
  1684.         tvxy(1,tvlins+1);    /* kill scrolled down line */
  1685.         tvelin();
  1686.         tvxy(1,1);
  1687.       }
  1688.       }
  1689.   }
  1690.  
  1691. /* =============================>>> TVXY   <<<============================= */
  1692.   tvxy(ix,iy)
  1693.   int ix,iy;
  1694.   {  /* tvxy - position cursor at position x,y 
  1695.         x=0 is left most column
  1696.         y=0 is top most line    */
  1697.  
  1698. #ifdef TERMCAP            /* TERMCAP different */
  1699.  
  1700.     tvx=ix;
  1701.     tvy=iy;
  1702.     tcapxy(ix,iy);        /* call termcap version of xy */
  1703.  
  1704. #else                /* generic version of tvxy */
  1705.  
  1706.     SLOW int x,y, coord1, coord2;
  1707.     FAST int i;
  1708.     SLOW char chrrep[4];
  1709.  
  1710.     x = min(ix+addx,tvcols+addx);    /* column is addx */
  1711.     y = iy+addy;            /* same for row */
  1712.     tvx = ix;
  1713.     tvy = iy;
  1714.  
  1715.     sendcs(cxybeg);        /* opening control sequence */
  1716.     if (cxy1st == 'l')
  1717.       {
  1718.     coord1 = y ; coord2 = x;
  1719.       }
  1720.     else
  1721.       {
  1722.     coord1 = x ; coord2 = y;
  1723.       }
  1724.  
  1725.     if (cxychr)
  1726.       {
  1727.     itoa(coord1,chrrep);
  1728.     sendcs(chrrep);
  1729.       }
  1730.     else
  1731.     tvcout(coord1);
  1732.  
  1733.     sendcs(cxymid);        /* middle control sequence */
  1734.  
  1735.     if (cxychr)
  1736.       {
  1737.     itoa(coord2,chrrep);
  1738.     sendcs(chrrep);
  1739.       }
  1740.     else
  1741.     tvcout(coord2);
  1742.  
  1743.     sendcs(cxyend);        /* send terminating sequence */
  1744.  
  1745. #endif                /* end of gerneric version */
  1746.   }
  1747.  
  1748. /* =============================>>> SENDCS <<<============================= */
  1749.   sendcs(cs)
  1750.   char cs[];
  1751.   {    /* send a control sequencs to terminal */
  1752.  
  1753.     FAST int i;
  1754.  
  1755. #ifndef UNIX
  1756.  
  1757.     for (i = 0 ; cs[i] ; ++i)
  1758.     tvcout(cs[i]);
  1759. #else                /* unix version */
  1760.  
  1761. #ifdef TERMCAP            /* termcap uses special output */
  1762.     tcapcs(cs);            /* send control string to termcap */
  1763. #else
  1764.     i = strlen(cs);
  1765.     tvlout(cs,i);
  1766. #endif                /* terminal specific unix version */
  1767.  
  1768. #endif                /* end of unix version */
  1769.   
  1770.   }
  1771.  
  1772. /* =============================>>> GKBD   <<<============================= */
  1773.   gkbd(chr)
  1774.   char *chr;
  1775.   {  /* gkbd - get one character from the keyboard */
  1776.  
  1777. #ifdef VB
  1778.     if (!bakflg)
  1779.       {
  1780. #endif
  1781.     do 
  1782.       {
  1783.         *chr = ttrd();    /* read only if non-backup version */
  1784.       }
  1785.     while (*chr == 0);    /* ignore EOS character */
  1786. #ifdef VB
  1787.       }
  1788.     else
  1789.     getbak(chr);
  1790.     putbak(*chr);    /* save to backup file */
  1791. #endif
  1792.   }
  1793.  
  1794. #ifndef UNIX
  1795. /* =============================>>> TTWTLN <<<============================= */
  1796.   ttwtln(chrbuf,len)
  1797.   char chrbuf[];
  1798.   int len;
  1799.   {  /*  write one line to terminal, generic version, unix uses its own */
  1800.  
  1801.     FAST int i;
  1802.  
  1803.     for (i = 0 ; i < len ; i++)
  1804.     ttwt(chrbuf[i]);
  1805.   } 
  1806. #endif
  1807.  
  1808. #ifdef CPM
  1809. /* ===========================>>> DISPCH <<<============================== */
  1810.   dispch(chr)
  1811.   char chr;
  1812.   {
  1813.  
  1814.     bdos(2,chr);    /* cp/m, ms-dos version */
  1815.   }
  1816. #endif
  1817. #ifdef MSDOS
  1818. #ifndef IBMPC
  1819. /* ===========================>>> DISPCH <<<============================== */
  1820.   dispch(chr)
  1821.   char chr;
  1822.   {
  1823.  
  1824.     bdos(2,chr);    /* cp/m, ms-dos version */
  1825.   }
  1826. #endif
  1827. /* =============================>>> USER_1 <<<============================= */
  1828.   user_1(knt)
  1829.   int knt;
  1830.   {
  1831.     knt = 0;
  1832.     return (TRUE);
  1833.   }
  1834.  
  1835. /* =============================>>> USER_2 <<<============================= */
  1836.   user_2(knt)
  1837.   int knt;
  1838.   {
  1839.     knt = 0;
  1840.     return (TRUE);
  1841.   }
  1842. #endif
  1843.  
  1844. #ifdef GEMDOS
  1845. /* ===========================>>> DISPCH <<<============================== */
  1846.   dispch(chr)
  1847.   char chr;
  1848.   {
  1849.  
  1850.     gemdos(2,chr);    /* cp/m, ms-dos version */
  1851.   }
  1852.  
  1853. /* =============================>>> USER_1 <<<============================= */
  1854.   user_1(knt)
  1855.   int knt;
  1856.   {
  1857.     knt = 0;
  1858.     return (TRUE);
  1859.   }
  1860.  
  1861. /* =============================>>> USER_2 <<<============================= */
  1862.   user_2(knt)
  1863.   int knt;
  1864.   {
  1865.     knt = 0;
  1866.     return (TRUE);
  1867.   }
  1868. #endif
  1869. /* ---------------------------- tvx_io.c ------------------------------- */
  1870.